home *** CD-ROM | disk | FTP | other *** search
/ EnigmA Amiga Run 1995 November / EnigmA AMIGA RUN 02 (1995)(G.R. Edizioni)(IT)[!][issue 1995-11][Skylink CD].iso / earcd / gfx / jpegaga2.lha / jpegAGAsrc / ppm2aga / EncodeHAM.asm < prev    next >
Assembly Source File  |  1995-01-08  |  19KB  |  470 lines

  1. ; ppm2AGA utility functions written by Günther Röhrich
  2.  
  3. ; the version for 68020+ processors is slightly faster and smaller
  4. ; the function is called from C:
  5. ; EncodeHAM(char *yorig, char *yham, char *ColorTable,
  6. ;            short NumColors, short xsize);
  7. ; yorig       = original row in rgbrgb... format
  8. ; yham        = row in HAM chunky format
  9. ; ColorTable  = color table in brgbrg... format
  10. ; NumColors   = (number of valid colors in ColorTable)*3
  11. ; xsize       = size of row in pixels
  12. ; ConvertMode should contain: 0 for HAM6 encoding
  13. ;                             1 for HAM8 encoding
  14.  
  15. ; int MapColor(colorhist_vector colormap, pixval r1, pixval g1, pixval b1,
  16. ;              int NumColors) 
  17. ; see later
  18.  
  19.  
  20.     IFD MC68020
  21.       MACHINE MC68020
  22.     ENDC
  23.  
  24.     IFD MC68000
  25.       MACHINE MC68000
  26.     ENDC
  27.  
  28.  
  29. ;NOTE: GCC stores all data as 32 bit at subroutine calls!
  30.  
  31. yorig        EQU 44  ;pointer to actual row (original)
  32. yham         EQU 48  ;pointer to actual row (HAM)
  33. ColorTable   EQU 52  ;address of color table (3 bytes per entry)
  34.  IFD GCC
  35. NumColors    EQU 58
  36. xsize        EQU 62
  37.  ELSE
  38. NumColors    EQU 56  ;number of colors allocated so far (*3)
  39. xsize        EQU 58  ;number of pixels (x)
  40.  ENDC
  41.  
  42. colormap   EQU 44  ;pointer to colorhist_vector
  43.  IFD GCC
  44. r1         EQU 51
  45. g1         EQU 55
  46. b1         EQU 59
  47. NColors    EQU 60
  48.  ELSE
  49. r1         EQU 48  ;red component (byte format)
  50. g1         EQU 50  ;green component
  51. b1         EQU 52  ;blue component
  52. NColors    EQU 54  ;number of colors in colormap
  53.  ENDC
  54.  
  55.     
  56.         XREF _Mult_Table  ;address of multiplication table
  57.         XREF _Mult_Table32
  58.         XREF _ConvertMode        ;HAM8 or HAM6
  59.         XDEF _EncodeHAM  ;entry point for function
  60.         XDEF _MapColorASM
  61.         XREF _ColorCache ;an 256K array
  62.  
  63. *       XDEF _blue_left ;only for debugging purposes
  64. *       XDEF _search_finish ;only for debugging
  65.         XDEF _MaxError
  66.         XDEF _MaxErrorPos 
  67.         XDEF _hit       ;only for debugging
  68.         XDEF _t1        ;only for debugging        
  69.  
  70.                dseg
  71.  
  72.  cnop 0,2
  73. _blue_left:      dc.b 0  ;this order is better for HAM-encoding
  74. _red_left:       dc.b 0
  75. _green_left:     dc.b 0,0 ;additional dummy-value for faster longword access
  76.  
  77.  cnop 0,2
  78. _offset_orig:   dc.w 0
  79. _offset_ham:    dc.w 0
  80. _MaxError:      dc.w 0
  81. _MaxErrorPos    dc.w 0
  82. _CacheOffset    dc.l 0
  83. _colcount       dc.w 2 
  84.       
  85.         cseg
  86.  
  87. ;register usage:   D0 = general purpose register
  88. ;                  D1 = contains afterwards the error
  89. ;                  D2 = orig_blue
  90. ;                  D3 = orig_red
  91. ;                  D4 = orig_green
  92. ;                  D5 = color that should be set
  93. ;                  D6 = offset to actual pixel (HAM)
  94. ;                  D7 = offset for color table / (0,1,2) at HAM
  95. ;                  A0 = best color so far (color+1)*3
  96. ;                  A1 = pointer to multiplication table
  97. ;                  A2 = pointer to color table / to _blue_left
  98. ;                  A3 = smallest error that has been reached so far
  99. ;                  A4 = used by the Aztec assembler (small data model)
  100. ;                  A5 = pointer to the actual row (original)
  101. ;                  A6 = pointer to the actual row (HAM)
  102.  
  103. ;WARNING: This will not work with color values higher than 63
  104. ;(HAM8 has a maximum of 63, HAM6 has a maximum of 15)
  105. ;(values higher than 63 may result in memory corruption)
  106.  
  107. ;computing the difference of color values is done with signed 8 bit
  108. ;arithmetic 
  109.  
  110. ;the maximum error value is 63^2+63^2+63^2=11907
  111. ;the summation has to be done therefore with 16 bits
  112.  
  113.  
  114. ;Initializing
  115. _EncodeHAM:     movem.l D2-D7/A2-A3/A5/A6,-(A7)  ;store registers
  116.                 lea     _blue_left,A0      ;load start of left colors
  117.                 move.l  ColorTable(sp),A2
  118.                 IFD MC68020
  119.                   move.l  (A2),(A0)
  120.                 ELSE
  121.                   move.b  (A2)+,(A0)+      ;initialize left colors
  122.                   move.b  (A2)+,(A0)+      ;A2 may not be word aligned
  123.                   move.b  (A2)+,(A0)+
  124.                   lea     -3(A0),A0        ;correct register
  125.                   lea     -3(A2),A2        ;correct register
  126.                 ENDC
  127.                 moveq.l #0,D6              ;initialize ham offset
  128.                 move.l  D6,_MaxError       ;initialize absolute max error
  129.                                            ;and max error pos      
  130.                 move.l  yham(sp),A6                           
  131.                 move.l  yorig(sp),A5
  132.                 lea     _Mult_Table,A1
  133.                 lea     255*2(A1),A1              
  134. search_begin:   move.b  (A5)+,D3           ;load registers with original colors
  135.                 move.b  (A5)+,D4           ;for faster access
  136.                 move.b  (A5)+,D2
  137.         IFD GCC
  138.                  lea     1(A5),A5          ;adjust A5 for correct alignment
  139.                 ENDC                       ;needed for GNU C
  140.                 move.w  #15000,A3          ;dummy-value for minimum error so far
  141.                 move.l  ColorTable(sp),A2
  142.                 moveq.l #0,D7              ;initialize offset for color table
  143.  
  144. ;find out if the new pixel has the same color as the previous one
  145.  
  146.                 lea      _blue_left,A0
  147.                 cmp.b    (A0),D2
  148.                 bne.s    search_cont
  149.                 cmp.b    1(A0),D3
  150.                 bne.s    search_cont
  151.                 cmp.b    2(A0),D4
  152.                 bne.s    search_cont
  153.  
  154. ;the new pixel has the same color, let's do a special encoding
  155.  
  156.                 move.w   _colcount,D7
  157.                 move.b   0(A0,D7.w),D5      
  158.                 subq.w   #1,_colcount
  159.                 bpl.s    ham6_9
  160.                 move.w  #2,_colcount
  161.                 bra.s    ham6_9
  162.  
  163.  
  164. ;First take a look if we have the value already in the cache
  165. search_cont:    moveq.l  #0,D0
  166.                 moveq.l  #0,D1             
  167.                 move.b   D3,D0             ;compute the cache offset
  168.                 lsl.l    #6,D0
  169.                 or.b     D4,D0
  170.                 lsl.l    #6,D0
  171.                 or.b     D2,D0             ;now we have the offset in D0
  172.                 movea.l  _ColorCache,A0    ;load start address of the cache
  173.                 move.b   0(A0,D0.l),D1     ;take the value from the cache
  174.                 bne     _hit               ;jump if we have a cache hit
  175.                 
  176.                 move.l   D0,_CacheOffset   ;store the offset to avoid recomputing it
  177.                 move.l   #3,A0             ;dummy-value for best colornumber so far
  178.                                            ; (3 means color 0)
  179.  
  180. search_start:    bsr      _compute_error
  181.                 cmp.w    D1,A3              ;A3 <= D1 ?
  182.                 bls.s    search4
  183.                 move.w   D1,A3              ;D1 is smaller than A3, store it
  184.                 move.w   D7,A0              ;store color number     
  185.                 tst.w    D1                 ;do we have the correct color ?
  186.                 beq      search5            ;then finish immediately
  187. search4:        cmp.w    NumColors(sp),D7   ;have we reached highest colornum ?
  188.                 bne.s    search_start       ;no, then once again                   
  189.                                         
  190. ;A0 contains now (colornumber+1)*3
  191. ;A3 contains the error for that colornumber
  192.  
  193. _t1:            move.w   A0,D0        
  194.                 movea.l  _ColorCache,A2
  195.                 move.l   _CacheOffset,D1
  196.                 move.b   D0,0(A2,D1.l)      ;store the value in the cache                
  197.                 lea      _blue_left,A2      ;restore A2
  198.  
  199. ;compute the error when using modify mode
  200.  
  201. start_ham6:     move.b   D2,D0              ;load orig_blue
  202.                 moveq.l  #0,D7              ;assume blue should be changed
  203.                 move.b   D2,D5              ;store value to change
  204.                 sub.b    _blue_left,D0      ;D0=D0-_blue_left
  205.                 bpl.s    ham6_1
  206.                 neg.b    D0                 ;make result positive
  207. ham6_1:         move.b   D0,D1              ;store maximum error so far
  208.                 move.b   D3,D0              ;load orig_red
  209.                 sub.b    _red_left,D0       ;D0=D0-_red_left
  210.                 bpl.s    ham6_2
  211.                 neg.b    D0              
  212. ham6_2:         cmp.b    D0,D1              ;check D1-D0
  213.                 bge.s    ham6_3             ;jump if D1>=D0
  214.                 move.b   D0,D1              ;store new maximum error
  215.                 moveq.l  #1,D7              ;assume red should be changed
  216.                 move.b   D3,D5              ;store value to change
  217. ham6_3:         move.b   D4,D0              ;load orig_green
  218.                 sub.b    _green_left,D0     ;D0=D0-_green_left
  219.                 bpl.s    ham6_4
  220.                 neg.b    D0
  221. ham6_4:         cmp.b    D0,D1
  222.                 bge.s    ham6_5
  223.                 move.b   D0,D1              ;store maximum error
  224.                 moveq.l  #2,D7              ;green should be changed
  225.                 move.b   D4,D5              ;store value to change
  226. ham6_5:         lea      _blue_left,A2      
  227.                 move.b   D5,0(A2,D7.W)      ;perform change
  228.  
  229. ham_error:      moveq.l  #0,D1
  230.                 moveq.l  #0,D0
  231.                 move.b   D2,D0              ;load blue_origin
  232.                 sub.b    (A2)+,D0           ;D0 = blue_color - blue_origin
  233.                 ext.w    D0
  234.                 IFD MC68020
  235.                   add.w    0(A1,D0.W*2),D1
  236.                 ELSE
  237.                   add.w    D0,D0            
  238.                   add.w    0(A1,D0.W),D1    ;D1 = D1 + D0*D0
  239.                 ENDC
  240.                 move.b   D3,D0              ;load red_origin
  241.                 sub.b    (A2)+,D0           ;D0 = red_color - red_origin 
  242.                 ext.w    D0
  243.                 IFD MC68020
  244.                   add.w    0(A1,D0.W*2),D1
  245.                 ELSE
  246.                   add.w    D0,D0
  247.                   add.w    0(A1,D0.W),D1
  248.                 ENDC
  249.                 move.b   D4,D0              ;load green_origin
  250.                 sub.b    (A2)+,D0           ;D0 = green_color - green_origin
  251.                 ext.w    D0
  252.                 IFD MC68020
  253.                   add.w    0(A1,D0.W*2),D1
  254.                 ELSE
  255.                   add.w    D0,D0
  256.                   add.w    0(A1,D0.W),D1    ;D1 contains error from HAM encoding
  257.                 ENDC
  258.  
  259.                 cmpa.w   D1,A3              ;check what error is smaller
  260.                 bls.s    _search_finish     ;jump if colortable is better
  261.                 cmp.w    _MaxError,D1       ;compare with absolute max error
  262.                 ble.s    ham6_9             ;jump if _MaxError is greater
  263.                 cmp.w    #2,D6              ;less then 2 pixels from left ?
  264.                 bpl.s    ham6_8a
  265.                 lsr.w    #1,D1              ;half error
  266. ham6_8a:        move.w   D1,_MaxError       
  267.                 move.w   D6,_MaxErrorPos
  268. ham6_9:         add.b    #1,D7              ;needed to get correct code
  269.                 tst.w    _ConvertMode       ;ConvertMode = 0  -> HAM6
  270.                 beq.s    ham6_10            ;ConvertMode != 0 -> HAM8
  271.                 IFD MC68020
  272.                   lsl.b    #2,D7            ;HAM8-adjust
  273.                 ELSE
  274.                   add.b    D7,D7            ;this is faster than shifting
  275.                   add.b    D7,D7            ;on the 68000
  276.                 ENDC
  277. ham6_10:        lsl.b    #4,D7              ;HAM6-adjust                      
  278.                 or.b     D5,D7
  279.                 move.b   D7,(A6,D6.W)       ;store code in bitmap
  280.  
  281.                 addq.w   #1,D6              ;increase _offset_ham
  282.                 cmp.w    xsize(sp),D6       ;end of column ?
  283.                 bne      search_begin
  284.                 bra.s    search_end
  285.  
  286. _search_finish: move.w   A3,D0              ;move error to D0
  287.                 cmp.w    #2,D6              ;less then 2 pixels from left ?
  288.                 bpl.s    _search_finish1
  289.                 lsr.w    #1,D0              ;half error
  290. _search_finish1: cmp.w    _MaxError,D0      ;compare with absolute max error
  291.                 ble.s    _search_finish2
  292.                 move.w   D0,_MaxError
  293.                 move.w   D6,_MaxErrorPos
  294. _search_finish2: move.w   A0,D0
  295.                 move.l   ColorTable(sp),A2
  296.                 lea      -3(A2,D0.W),A3     ;load A3 with pointer to colors
  297.                 divu     #3,D0
  298.                 subq.w   #1,D0
  299.                 move.b   D0,0(A6,D6.W)      ;store colornumber in bitmap
  300.                 lea      _blue_left,A2
  301.                 IFD MC68020
  302.                   move.l   (A3),(A2)
  303.                 ELSE
  304.                   move.b   (A3)+,(A2)+      ;store new left colors
  305.                   move.b   (A3)+,(A2)+      ;A3 may not be word aligned
  306.                   move.b   (A3)+,(A2)+      ;
  307.                 ENDC
  308.                 addq.w   #1,D6              ;increase _offset_ham
  309.                 cmp.w    xsize(sp),D6       ;have we reached the end ?
  310.                 bne      search_begin
  311.  
  312. search_end:     movem.l  (A7)+,D2-D7/A2-A3/A5/A6  ;restore registers
  313.                 rts                         ;jump back to caller
  314.                 
  315.  
  316.  
  317. ;we jump here if we have reached error 0 by colortable only
  318. ;and there was not a cache hit
  319. search5:        move.w   A0,D0         
  320.                 movea.l  _ColorCache,A2
  321.                 move.l   _CacheOffset,D1
  322.                 move.b   D0,0(A2,D1.l)      ;store the value in the cache                
  323.                 bra.s    _search_finish
  324.  
  325.  
  326. ;we jump here if we have a cache hit
  327. ;D1 contains the best color number, but we have to compute the error
  328.  
  329. _hit:           subq.w   #3,D1              ;correct color number
  330.                 move.w   D1,D7
  331.                 bsr.s    _compute_error
  332.         move.w   D1,A3              ;D1 is smaller than A3, store it
  333.                 move.w   D7,A0              ;store color number     
  334.                 bra      start_ham6         ;continue with HAM encoding
  335.  
  336.  
  337. ;compute the error
  338.  
  339.  
  340. _compute_error: moveq.l  #0,D1
  341.                 moveq.l  #0,D0             
  342.                 move.b   D2,D0              ;load blue_origin
  343.                 sub.b    0(A2,D7.W),D0      ;D0 = blue_color - blue_origin
  344.                 ext.w    D0                 ;extend result to word
  345.                 IFD MC68020
  346.                   add.w    0(A1,D0.W*2),D1
  347.                 ELSE
  348.                   add.w    D0,D0            
  349.                   add.w    0(A1,D0.W),D1    ;D1 = D1 + D0*D0
  350.                 ENDC
  351.                 addq.w   #1,D7              ;advance color table offset
  352.                 move.b   D3,D0              ;load red_origin
  353.                 sub.b    0(A2,D7.W),D0      ;D0 = red_color - red_origin
  354.                 ext.w    D0
  355.                 IFD MC68020
  356.                   add.w    0(A1,D0.W*2),D1
  357.                 ELSE
  358.                   add.w    D0,D0
  359.                   add.w    0(A1,D0.W),D1
  360.                 ENDC
  361.                 addq.w   #1,D7              ;advance color table offset
  362.                 move.b   D4,D0              ;load green_origin
  363.                 sub.b    0(A2,D7.W),D0      ;D0 = green_color - green_origin
  364.                 ext.w    D0
  365.                 IFD MC68020
  366.                   add.w    0(A1,D0.W*2),D1  ;D1 = D1 + D0*D0
  367.                 ELSE
  368.                   add.w    D0,D0
  369.                   add.w    0(A1,D0.W),D1
  370.                 ENDC
  371.                 addq.w   #1,D7              ;advance color table offset
  372.         rts
  373.  
  374.                 
  375.  
  376.  
  377.  
  378.  
  379. ;now comes the brute-force colormap search code
  380. ;if you know how to make it faster/smaller please let me know
  381.  
  382. ;the 68020 main loop is only 56 bytes long, it should 
  383. ;fit completely into the 256 bytes instruction cache of the 68020
  384. ;or 68030 processor
  385.  
  386. ;NOTE: this is a bit different compared to the HAM-code because
  387. ;signed 8 bit math gives wrong results with values higher than 127
  388. ;it computes the differences therefore with 16 bit
  389.  
  390. ;the maximum error value is 3*255^2=195075, we will therefore need
  391. ;32 bit arithmetic for the summation
  392.  
  393. ;register usage:
  394. ;                 D0 = general purpose register, return value
  395. ;                 D1 = contains error
  396. ;                 D2 = r1
  397. ;                 D3 = g1
  398. ;                 D4 = b1
  399. ;                 D5 = holds color from colormap
  400. ;                 D6 = counter
  401. ;                 D7 = color table offset
  402. ;                 A1 = pointer to multiplication table
  403. ;                 A2 = pointer to colormap
  404. ;                 A3 = smallest error
  405. ;                 A5 = actual error
  406. ;                 A6 = NColors
  407.  
  408. _MapColorASM:   movem.l D2-D7/A2-A3/A5/A6,-(A7)  ;store registers
  409.                 move.l  colormap(sp),A2
  410.                 move.l  NColors(sp),A6
  411.                 lea     _Mult_Table32,A1
  412.                 lea     255*4(A1),A1
  413.                 moveq.l #0,D2               ;ensure that the higher bytes
  414.                 moveq.l #0,D3               ;of these registers are cleared
  415.                 moveq.l #0,D4  
  416.                 move.b  r1(sp),D2
  417.                 move.b  g1(sp),D3
  418.                 move.b  b1(sp),D4
  419.                 move.l  #2000000000,A3      ;dummy value for min. error 
  420.                 moveq.l #0,D6               ;initialize counter
  421.                 moveq.l #0,D7
  422.                 moveq.l #0,D5
  423.  
  424. ;now comes the main loop
  425.  
  426. Map_start:      suba.l   A5,A5              ;clear A5 (actual error)
  427.                 move.l   D2,D0              ;load r1
  428.                 move.b   0(A2,D7.W),D5      ;load colormap.red
  429.                 sub.w    D5,D0              ;D0 = colormap.red - r1
  430.                 IFD MC68020
  431.                   add.l    0(A1,D0.W*4),A5
  432.                 ELSE
  433.                   lsl.w    #2,D0            
  434.                   add.l    0(A1,D0.W),A5    ;A5 = A5 + D0*D0
  435.                 ENDC
  436.                 move.l   D3,D0              ;load g1
  437.                 move.b   1(A2,D7.W),D5      ;load colormap.green
  438.                 sub.w    D5,D0              ;D5 = colormap.green - g1
  439.                 IFD MC68020
  440.                   add.l    0(A1,D0.W*4),A5
  441.                 ELSE
  442.                   lsl.w    #2,D0
  443.                   add.l    0(A1,D0.W),A5
  444.                 ENDC
  445.                 move.l   D4,D0              ;load b1
  446.                 move.b   2(A2,D7.W),D5      ;load colormap.blue
  447.                 sub.w    D5,D0              ;D0 = colormap.blue - b1
  448.                 IFD MC68020               
  449.                   add.l    0(A1,D0.W*4),A5  ;A5 = A5 + D0*D0
  450.                 ELSE
  451.                   lsl.w    #2,D0
  452.                   add.l    0(A1,D0.W),A5
  453.                 ENDC
  454.                 addq.w   #8,D7              ;advance color table offset              
  455.               
  456.                 cmp.l    A5,A3              ;A3 - A5 ?
  457.                 bls.s    Map1
  458.                 move.l   A5,A3              ;D1 is smaller than A3, store it
  459.                 move.w   D6,A0              ;store color number     
  460.                 move.l   A5,D0              ;do we have the correct color ?
  461.                 beq.s    Map_finish         ;then finish immediately
  462. Map1:           addq.w   #1,D6              ;advance color number
  463.                 cmp.l    A6,D6              ;have we reached highest colornum ?
  464.                 bne.s    Map_start          ;no, then once again                                               
  465. Map_finish:     move.l   A0,D0              ;store return value
  466.                 movem.l  (A7)+,D2-D7/A2-A3/A5/A6  ;restore registers
  467.                 rts                         ;jump back to caller
  468. end
  469.  
  470.